using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SiKuma.ScreenSystemLibrary
{
    public abstract class GameScreen
    {
        public delegate void TransitionEventHandler(object sender, TransitionEventArgs tea);
        
        private float transitionDirection = 1f;
        private float transitionMultiplier = 1f;
        private TransitionState transitionState;
        private ScreenState state;
        private bool isContentLoaded;
        private bool isContentUnloaded;
        private bool isInitialized;
        private Texture2D fadeTexture;
        private Color fadeColor;
        private float fadeAmount;
        private bool fadeIsEnabled;
        
        public event GameScreen.TransitionEventHandler Entering;
        public event GameScreen.TransitionEventHandler Exiting;
        public event EventHandler Removing;
        
        public TimeSpan TransitionOnTime
        {
            get;
            set;
        }
        
        public TimeSpan TransitionOffTime
        {
            get;
            set;
        }
        
        public float TransitionPercent
        {
            get;
            private set;
        }
        
        public float TransitionDirection
        {
            get
            {
                return this.transitionDirection;
            }
        }
        
        public float TransitionMultiplier
        {
            get
            {
                return this.transitionMultiplier;
            }
            protected set
            {
                this.transitionMultiplier = value;
            }
        }
        
        public TransitionState TransitionState
        {
            get
            {
                return this.transitionState;
            }
        }
        
        public virtual float ScreenAlpha
        {
            get
            {
                return 1f;
            }
        }
        
        public ScreenState State
        {
            get
            {
                return this.state;
            }
            protected set
            {
                this.state = value;
            }
        }
        
        public bool IsActive
        {
            get
            {
                return this.state == ScreenState.TransitionOn || this.state == ScreenState.TransitionOff || this.state == ScreenState.Active;
            }
        }
        
        public ScreenSystem ScreenSystem
        {
            get;
            set;
        }
        
        public abstract bool AcceptsInput
        {
            get;
        }
        
        public bool IsContentLoaded
        {
            get
            {
                return this.isContentLoaded;
            }
        }
        
        public bool IsContentUnloaded
        {
            get
            {
                return this.isContentUnloaded;
            }
        }
        
        public InputMap InputMap
        {
            get;
            private set;
        }
        
        public void Initialize()
        {
            if (!this.isInitialized)
            {
                this.InputMap = new InputMap();
                this.isInitialized = true;
            }
        }
        
        public abstract void InitializeScreen();
        
        public virtual void LoadContent()
        {
            this.isContentLoaded = true;
        }
        
        public virtual void UnloadContent()
        {
            this.isContentUnloaded = true;
        }
        
        public void Update(GameTime gameTime)
        {
            InputSystem.Update(gameTime);
            if (this.state == ScreenState.Frozen || this.state == ScreenState.Inactive)
            {
                return;
            }
            if (this.state == ScreenState.TransitionOn)
            {
                float num = this.CalculateTransitionTime(this.TransitionOnTime, gameTime);
                this.TransitionPercent += num * this.transitionMultiplier;
                if ((double)this.TransitionPercent >= 1.0)
                {
                    this.TransitionPercent = 1f;
                    this.state = ScreenState.Active;
                    return;
                }
                if (this.Entering != null)
                {
                    this.Entering(this, new TransitionEventArgs(this.TransitionPercent, num));
                    return;
                }
            }
            else
            {
                if (this.state == ScreenState.TransitionOff)
                {
                    float num2 = this.CalculateTransitionTime(this.TransitionOffTime, gameTime);
                    this.TransitionPercent -= num2 * this.transitionMultiplier;
                    if (this.TransitionPercent <= 0f)
                    {
                        this.TransitionPercent = 0f;
                        this.Remove();
                        return;
                    }
                    if (this.Exiting != null)
                    {
                        this.Exiting(this, new TransitionEventArgs(this.TransitionPercent, num2));
                        return;
                    }
                }
                else
                {
                    if (this.state == ScreenState.Active || this.state == ScreenState.Hidden)
                    {
                        this.UpdateScreen(gameTime);
                    }
                }
            }
        }
        
        private float CalculateTransitionTime(TimeSpan transitionTime, GameTime gameTime)
        {
            if (transitionTime == TimeSpan.Zero)
            {
                return 1f;
            }
            return (float)(gameTime.ElapsedGameTime.TotalSeconds / transitionTime.TotalSeconds);
        }
        
        protected abstract void UpdateScreen(GameTime gameTime);
        
        public virtual void HandleInput()
        {
        }
        
        public void Draw(GameTime gameTime)
        {
            if (this.state != ScreenState.Inactive && this.state != ScreenState.Hidden)
            {
                SpriteBatch spriteBatch = this.ScreenSystem.SpriteBatch;
                spriteBatch.Begin();
                if (this.fadeIsEnabled)
                {
                    Viewport viewport = this.ScreenSystem.Viewport;
                    spriteBatch.Draw(this.fadeTexture, new Rectangle(0, 0, viewport.Width, viewport.Height), this.fadeColor);
                }
                this.DrawScreen(gameTime);
                spriteBatch.End();
            }
        }
        
        protected abstract void DrawScreen(GameTime gameTime);
        
        public void ExitScreen()
        {
            this.state = ScreenState.TransitionOff;
            this.transitionDirection = -1f;
        }
        
        private void Remove()
        {
            this.ScreenSystem.RemoveScreen(this);
            if (this.Removing != null)
            {
                this.Removing(this, EventArgs.Empty);
            }
        }
        
        public void FreezeScreen()
        {
            this.state = ScreenState.Frozen;
        }
        
        public void ActivateScreen()
        {
            if (this.state != ScreenState.Inactive && this.state != ScreenState.Active)
            {
                this.state = ScreenState.Active;
            }
        }
        
        public void EnableFade(Color c, float percentage)
        {
            percentage = MathHelper.Clamp(percentage, 0f, 1f);
            this.fadeAmount = percentage;
            this.fadeTexture = new Texture2D(this.ScreenSystem.GraphicsDevice, 1, 1);
            Color[] data = new Color[]
			{
				c
			};
            this.fadeTexture.SetData<Color>(data);
            this.fadeColor = c * percentage;
            this.fadeIsEnabled = true;
        }
        
        public void DisableFade()
        {
            this.fadeTexture = null;
            this.fadeColor = Color.White;
            this.fadeIsEnabled = false;
        }
    }
}
